package com.spring.sunflower.widget;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;

import androidx.core.content.ContextCompat;

import com.spring.sunflower.R;
import com.spring.sunflower.util.DisplayUtils;
import com.spring.sunflower.util.LogUtils;

import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class LineWaveVoiceView extends View {
    private static final String DEFAULT_TEXT = " 请录音 ";
    private static final int LINE_WIDTH = 9;//默认矩形波纹的宽度，9像素, 原则上从layout的attr获得
    private Paint paint = new Paint();
    private Runnable task;
    private ExecutorService executorService = Executors.newCachedThreadPool();
    private RectF rectRight = new RectF();//右边波纹矩形的数据，10个矩形复用一个rectF
    private RectF rectLeft = new RectF();//左边波纹矩形的数据
    private RectF rectF = new RectF();
    private String text = DEFAULT_TEXT;
    private int updateSpeed;
    private int lineColor;
    private int textColor;
    private float lineWidth;
    private float textSize;
    private int mDefaultHeight;
    private int mDefaultWidth;
    public LineWaveVoiceView(Context context) {
        super(context);
    }

    public LineWaveVoiceView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public LineWaveVoiceView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView(attrs, context);
        resetView(mWaveList, DEFAULT_WAVE_HEIGHT);
        task = new LineJitterTask();
    }

    private void initView(AttributeSet attrs, Context context) {
        //获取布局属性里的值
        TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.LineWaveVoiceView);
        lineColor = mTypedArray.getColor(R.styleable.LineWaveVoiceView_voiceLineColor, ContextCompat.getColor(context, R.color.white));
        lineWidth = mTypedArray.getDimension(R.styleable.LineWaveVoiceView_voiceLineWidth, LINE_WIDTH);
        textSize = mTypedArray.getDimension(R.styleable.LineWaveVoiceView_voiceTextSize, 42);
        textColor = mTypedArray.getColor(R.styleable.LineWaveVoiceView_voiceTextColor, ContextCompat.getColor(context, R.color.white));
        updateSpeed = mTypedArray.getInt(R.styleable.LineWaveVoiceView_updateSpeed, UPDATE_INTERVAL_TIME);
        mTypedArray.recycle();
        mDefaultWidth = (int) (lineWidth*20);
        mDefaultHeight = DisplayUtils.dip2px(getContext(), 30);
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = measureWidth(widthMeasureSpec);
        int height = measureHeight(heightMeasureSpec);
        setMeasuredDimension(width, height);
    }

    private int measureWidth(int measureSpec) {
        int result = mDefaultWidth;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);
        switch (specMode) {
            case MeasureSpec.UNSPECIFIED:
                result = specSize;
                break;
            case MeasureSpec.AT_MOST:
                result = Math.min(result, specSize);
                break;
            case MeasureSpec.EXACTLY:
                result = specSize;
                break;
        }
        return result;
    }
    private int measureHeight(int measureSpec) {
        int result = mDefaultHeight;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);
        switch (specMode) {
            case MeasureSpec.UNSPECIFIED:
                result = Math.min(result, specSize);
                break;
            case MeasureSpec.AT_MOST:
                result = Math.min(result, specSize);
                break;
            case MeasureSpec.EXACTLY:
                result = specSize;
                break;
        }
        return result;
    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //获取实际宽高的一半
        int widthCentre = getWidth() / 2;
        int heightCentre = getHeight() / 2;
        paint.setStrokeWidth(0);
        paint.setColor(textColor);
        paint.setTextSize(textSize);
        float textWidth = paint.measureText(text);
//        canvas.drawText(text, widthCentre - textWidth / 2, heightCentre - (paint.ascent() + paint.descent()) / 2, paint);

        //设置颜色
        paint.setColor(lineColor);
        //填充内部
        paint.setStyle(Paint.Style.FILL);
        //设置抗锯齿
        paint.setAntiAlias(true);
        canvas.save();
        canvas.translate((getWidth()-lineWidth*19)/2,0);
        LogUtils.INSTANCE.logD("LineWave", "onDraw");
        for (int i = 0; i < 10; i++) {
            rectF.left = i * 2 * lineWidth;
            rectF.right = i * 2 * lineWidth + lineWidth;
            rectF.top = heightCentre - mWaveList.get(i) / 2;
            LogUtils.INSTANCE.logD("LineWave", "onDraw " + i + "=" + rectF.top + ",heightCentre=" + heightCentre + ",mWaveList.get(i)" + mWaveList.get(i));
            rectF.bottom = heightCentre + mWaveList.get(i) / 2;
            canvas.drawRoundRect(rectF, 6, 6, paint);
//            rectF.top = heightCentre-

//            rectRight.left = widthCentre + textWidth / 2 + (1 + 2 * i) * lineWidth;
//            rectRight.top = heightCentre - lineWidth * mWaveList.get(i) / 2;
//            LogUtils.INSTANCE.logD("LineWave", "onDraw " + i + "=" + rectRight.top);
//            rectRight.right = widthCentre + textWidth / 2 + (2 + 2 * i) * lineWidth;
//            rectRight.bottom = heightCentre + lineWidth * mWaveList.get(i) / 2;
//
//            //左边矩形
//            rectLeft.left = widthCentre - textWidth / 2 - (2 + 2 * i) * lineWidth;
//            rectLeft.top = heightCentre - mWaveList.get(i) * lineWidth / 2;
//            rectLeft.right = widthCentre - textWidth / 2 - (1 + 2 * i) * lineWidth;
//            rectLeft.bottom = heightCentre + mWaveList.get(i) * lineWidth / 2;
//
//            canvas.drawRoundRect(rectRight, 6, 6, paint);
//            canvas.drawRoundRect(rectLeft, 6, 6, paint);
        }
        canvas.restore();
    }

    private static final int MIN_WAVE_HEIGHT = 2;//矩形线最小高
    private static final int MAX_WAVE_HEIGHT = 12;//矩形线最大高
    private static final int[] DEFAULT_WAVE_HEIGHT = {10, 10, 10, 10, 10, 10, 10, 10, 10, 10};
    private static final int UPDATE_INTERVAL_TIME = 100;//100ms更新一次
    private LinkedList<Integer> mWaveList = new LinkedList<>();
    private float maxDb;

    private void resetView(List<Integer> list, int[] array) {
        list.clear();
        for (int anArray : array) {
            list.add(anArray);
        }
    }

    private synchronized void refreshElement() {
        Random random = new Random();
        maxDb = random.nextInt(5) + 2;
        int waveH = MIN_WAVE_HEIGHT + Math.round(maxDb * (MAX_WAVE_HEIGHT - MIN_WAVE_HEIGHT));
        LogUtils.INSTANCE.logD("LineWave", "waveH=" + waveH);
        mWaveList.add(0, waveH);
        LogUtils.INSTANCE.logD("LineWave", "waveList.size=" + mWaveList.size());
        mWaveList.removeLast();
        postInvalidate();
    }

    public boolean isStart = false;

    private class LineJitterTask implements Runnable {
        @Override
        public void run() {
            while (isStart) {
                refreshElement();
                try {
                    Thread.sleep(updateSpeed);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                postInvalidate();
            }
        }
    }

    public synchronized void startRecord() {
        isStart = true;
        executorService.execute(task);
    }

    public synchronized void stopRecord() {
        isStart = false;
        mWaveList.clear();
        resetView(mWaveList, DEFAULT_WAVE_HEIGHT);
        postInvalidate();
    }


    public synchronized void setText(String text) {
        this.text = text;
        postInvalidate();
    }

    public void setUpdateSpeed(int updateSpeed) {
        this.updateSpeed = updateSpeed;
    }
}